﻿module Sustainalytics.Insights {

    export class InsightsAddEditController {

        // controller scope
        public $scope: ng.IScope;
        // services
        private $q: ng.IQService;
        private $location: ng.ILocationService;
        private $routeParams: ng.route.IRouteParamsService;
        private notificationFactory: INotificationFactory;
        private backendService: InsightsBackendService;
        private staticObjects: IStaticObjects;

        // specifies whether current controller is in loading state
        public isLoading: boolean;
        public insight: InsightDtoUi;
        public isEditDisabled: boolean;
        public tempImagePath: string;
        public isAddMode: boolean;

        private selectedFile: any;
        private imageWitdh: number = 200;
        private imageHeight: number = 251;
        //disable save button until the pdf/image upload
        public isSaveDisabled: boolean;

        public currentDate(): string {

            var dt = new Date();

            return "'" + dt.getFullYear() + "-" + (dt.getMonth() + 1) + "-" + dt.getDate() + "'";
        }

        public currentDatePlusOneDay(): string {

            var dt = new Date(Date.now() + 86400000);
            return "'" + dt.getFullYear() + "-" + (dt.getMonth() + 1) + "-" + dt.getDate() + "'";
        }

        // nomeclators list
        public topicNames: InsightTopicName[];
        public sectorNames: InsightSectorName[];

        constructor($scope: ng.IScope, $q: ng.IQService, $location: ng.ILocationService, $routeParams: ng.route.IRouteParamsService,
            backend: InsightsBackendService, notificationFactory: INotificationFactory, staticObjects: IStaticObjects) {

            var ctx = this;

            ctx.$scope = $scope;
            ctx.$q = $q;
            ctx.$location = $location;
            ctx.backendService = backend;
            ctx.notificationFactory = notificationFactory;
            ctx.staticObjects = staticObjects;
            ctx.$routeParams = $routeParams;

            ctx.isEditDisabled = false;
            ctx.isSaveDisabled = false;
            ctx.isAddMode = true;

            ctx.tempImagePath = "";

            // load all required data
            ctx.load();

            // scope
            $scope['insightAddEdit'] = ctx;

            // bind to load event in the hidden image

            $("#tmpImage").bind("load", this, ctx.onImagePreloaded);

            // notify parents that the controller was created
            $scope.$emit('insightList.created', ctx);
        }

        private load(): ng.IPromise<{}> {
            var ctx = this;

            ctx.isLoading = true;


            var promises = [];
            var nomenclatorsPromise = ctx.loadNomenclators();
            promises.push(nomenclatorsPromise);


            var insightId: string = ctx.$routeParams['id'];
            if (insightId) {
                ctx.isAddMode = false;
                var loadInsightPromise = ctx.loadInsight(insightId);
                promises.push(loadInsightPromise);
            }

            var allPromise = ctx.$q.all(promises);
            allPromise.finally(() => { ctx.isLoading = false; });
            return allPromise;
        }

        private loadNomenclators(): ng.IPromise<InsightHelperDto> {

            var ctx = this;
            var getPromise: ng.IPromise<InsightHelperDto> = ctx.backendService.getNomenclators();
            getPromise.then((helper: InsightHelperDto) => {

                if (helper) {
                    ctx.topicNames = helper.topicNames;
                    ctx.sectorNames = helper.sectorNames.sort((a, b) => {
                        if (a.name > b.name)
                            return 1;
                        if (a.name < b.name)
                            return -1;

                        return 0;
                    });
                }
            });
            return getPromise;
        }

        private loadInsight(id: string): ng.IPromise<InsightDtoUi> {

            var ctx = this;
            var getPromise: ng.IPromise<InsightDtoUi> = ctx.backendService.insightGet(id);
            getPromise.then((insight: InsightDtoUi) => {
                ctx.insight = insight;
                ctx.isEditDisabled = (ctx.insight.state != 0);
            });
            return getPromise;
        }

        private IsSummaryValid(): number {
            var ctx = this;

            var newText = $("#insightSummary").text().replace("H1H2H3Toggle HTML", "");
            newText = newText.replace("\n", "");
            newText = newText.trim();

            if (newText.length == 0) {
                return 2111;
            }

            if (newText.length > 5000) {
                return 2112;
            }
            return null;
        }

        private IsFormValid(): boolean {

            var ctx = this;

            var form = ctx.$scope['insightAddEditForm'];

            var isSummaryError = ctx.IsSummaryValid();

            var isFormvalid = form['sectorSelect']['$valid'] &&
                form['topicSelect']['$valid'] &&
                form['insightTitle']['$valid'] &&
                form['insightImage']['$valid'] &&
                form['insightFile']['$valid'] &&
                form['insightSummary']['$valid'] &&
                isSummaryError != 2111 &&
                isSummaryError != 2112 &&
                form['insightDatePublished']['$valid'] &&
                form['insightDateUnPublished']['$valid'];

            // check if the form is valid
            if (!isFormvalid || !ctx.IsValidDateRange()) {
                ctx.showValidationMessages();
                return false;
            }
            return true;
        }

        public cancel() {
            var ctx = this;
            var def = ctx.$q.defer();

            if (!confirm('Are you sure you want to leave this page? All information will be lost.')) {
                def.resolve();
                return def.promise;
            }

            // notify operation cancelled
            ctx.$location.path('/insights');

            def.resolve();
            return def.promise;
        }

        public publish() {
            var ctx = this;

            
            // check if the form is valid
            if (!ctx.IsFormValid())
                return ctx.$q.when(false);
            

            // set status to draft
            ctx.insight.state = 1;// published

            var addPromise: ng.IPromise<boolean> = ctx.backendService.insightCreateOrUpdate(ctx.insight);
            addPromise.then((result: boolean) => {

                if (result) {
                    ctx.notificationFactory.success('Save succeeded.');
                    ctx.$location.path('/insights');
                }
                else {
                    ctx.notificationFactory.error('Save failed.', "");
                }
            });
            return addPromise;
        }

        public saveAsDraft(): ng.IPromise<boolean> {
            var ctx = this;

            // check if the form is valid
            if (!ctx.IsFormValid())
                return ctx.$q.when(false);

            // assure status to draft
            ctx.insight.state = 0;// draft

            var addPromise: ng.IPromise<boolean> = ctx.backendService.insightCreateOrUpdate(ctx.insight);
            addPromise.then((result: boolean) => {

                if (result) {
                    ctx.notificationFactory.success('Save succeeded.');
                    ctx.$location.path('/insights');
                }
                else {
                    ctx.notificationFactory.error('Save failed.', "");
                }
            });
            return addPromise;
        }

        //image upload
        private uploadImage(): ng.IPromise<{}> {
            var ctx = this;

            ctx.isSaveDisabled = true;
            var promise = ctx.backendService.fileUpload(ctx.selectedFile, ctx.insight.imageId);
            promise.then(
                //scuccess
                (data: { id: string; fileUrl: string; }) => {
                    ctx.$scope.$evalAsync(() => {
                        ctx.insight.imageId = data.id;
                        ctx.insight.imageUrl = data.fileUrl;
                        ctx.notificationFactory.success('Upload succeeded.');
                        $("#imageInsights").val('');
                        ctx.isSaveDisabled = false;
                    });
                },
                //error
                () => {
                    ctx.showErrorCode(2114);
                    $("#imageInsights").val('');
                    ctx.isSaveDisabled = false;
                }
                );
            return promise;
        }

        private onImagePreloaded(event) {

            var ctx = event.handleObj.data;
            var element = $("#tmpImage");
            element.removeClass("empty");
            var isValid = element.height() == ctx.imageHeight && element.width() == ctx.imageWitdh;
            if (isValid) {
                ctx.uploadImage();

            } else {

                $("#imageInsights").val('');
                ctx.showErrorCode(2110);
            }
        }

        public onSelectImage(files): any {

            var ctx = this;
            // is always one file - from html 
            var file = files[0];
            if (file.type == "image/jpeg" || file.type == "image/png" || file.type == "image/jpg") {

                var def = ctx.$q.defer();
                var reader = new FileReader();
                reader.onload = () => {
                    ctx.$scope.$evalAsync(() => {
                        ctx.tempImagePath = reader.result;
                        ctx.selectedFile = file;
                    });
                    def.resolve(true);
                }
                reader.readAsDataURL(file);// read like this in order to display 
                    
                ctx.$q.all([def.promise]);
            } else {
                $("#imageInsights").val('');
                ctx.showErrorCode(2110);
            }
        }

        // report upload
        public onSelectPDFReport(files): any {
            var ctx = this;

            ctx.isSaveDisabled = true;
            var file = files[0]; // html assures is just 1
            if (file) {
                if (file.size > 10 * 1024 * 1024 || file.type != "application/pdf") {
                    ctx.showErrorCode(2108);
                    $("#pdfInsights").val('');
                    ctx.isSaveDisabled = false;
                } else {

                    var promise = ctx.backendService.fileUpload(file, ctx.insight.fileId);
                    promise
                        .then(   
                        // success 
                        (data: { id: string; fileUrl: string; }) => {
                            ctx.$scope.$evalAsync(() => {

                                ctx.insight.fileId = data.id;
                                ctx.insight.fileUrl = data.fileUrl;
                                ctx.insight.fileName = file.name;
                            });
                            ctx.notificationFactory.success('Upload succeeded.');
                            $("#pdfInsights").val('');
                            ctx.isSaveDisabled = false;

                        },
                        //error
                        () => {

                            $("#pdfInsights").val('');
                            ctx.showErrorCode(2114);//todo reset values 
                            ctx.isSaveDisabled = false;
                        }
                        );
                }
            }
        }

        // show validation messages
        private showValidationMessages() {
            var ctx = this;

            var form = ctx.$scope['insightAddEditForm'];
            
            //// sectorid
            //var sectorSelect = form['sectorSelect'];
            //if (sectorSelect['$invalid']) {
            //    if (sectorSelect['$error']['required'])
            //        ctx.showErrorCode(2100);
            //    return;
            //}

            //// topic 
            //var topicSelect = form['topicSelect'];
            //if (topicSelect['$invalid']) {
            //    if (topicSelect['$error']['required'])
            //        ctx.showErrorCode(2101);
            //    return;
            //}

            // Title
            var insightTitle = form['insightTitle'];
            if (insightTitle['$invalid']) {
                if (insightTitle['$error']['required'])
                    ctx.showErrorCode(2102);
                else
                    if (insightTitle['$error']['maxlength'])
                        ctx.showErrorCode(2103);
                return;
            }

            // date publish
            var insightDatePublished = form['insightDatePublished'];
            if (insightDatePublished['$invalid']) {
                if (insightDatePublished['$error']['required'])
                    ctx.showErrorCode(2105);
                else
                    ctx.showErrorCode(2105);

                return;
            }

            // imageid
            var insightImage = form['insightImage'];
            if (insightImage['$invalid']) {
                if (insightImage['$error']['required'])
                    ctx.showErrorCode(2109);
                //ctx.showErrorCode(2110);
                return;
            }
            

            // fileid
            var insightFile = form['insightFile'];
            if (insightFile['$invalid']) {
                if (insightFile['$error']['required'])
                    ctx.showErrorCode(2107);
                //ctx.showErrorCode(2108);
                return;
            }

           
            // date un publish
            var insightDateUnPublished = form['insightDateUnPublished'];
            if (insightDateUnPublished['$invalid']) {
                if (insightDateUnPublished['$error']['required'])
                    ctx.showErrorCode(2105);
                else
                    ctx.showErrorCode(2105);

                return;
            }

            //todo validate dates publish < unpublish            
            if (!ctx.IsValidDateRange()) {
                ctx.showErrorCode(2113);
                return;
            }

            // summary
            var insightSummary = form['insightSummary'];
            var errorNumber = ctx.IsSummaryValid();
            console.log(errorNumber);
            if (insightSummary['$invalid'] || errorNumber != null) {
                ctx.showErrorCode(errorNumber);
                return;
            }
            //if (insightSummary['$invalid'] || !ctx.IsSummaryValid() ) {
            //    if (insightSummary['$error']['required'] || !ctx.IsSummaryValid())
            //        ctx.showErrorCode(2111);
            //    else
            //        if (insightTitle['$error']['maxlength'])
            //            ctx.showErrorCode(2112);

            //    return;
            //}
        }

        private IsValidDateRange(): boolean {

            var ctx = this;

            var p = new Date(Date.parse(ctx.insight.datePublished));
            var u = new Date(Date.parse(ctx.insight.dateUnPublished));
            var pDate = new Date(p.getFullYear(), p.getMonth(), p.getDate());
            var upDate = new Date(u.getFullYear(), u.getMonth(), u.getDate());


            return upDate.getTime() >= (pDate.getTime() + (24 * 60 * 60 * 1000));
        }

        // show error code
        // TO DO: staticObjects has dependency on notificationFactory but notificationFactory is used to send messages
        // notificationFactory should use staticObjects to write messages based on provided codes which messages can be located into staticObjects.
        // In this case we cannot do cyclic references and therefore this method was created.
        private showErrorCode(code: number) {
            var ctx = this;
            var msg = ctx.staticObjects.getMessageByInternalCode(code);
            ctx.notificationFactory.error('', msg);
        }
    } 


    // register controller with News Angular module
    angular.module('Sustainalytics.Insights')
        .controller('InsightsAddEditController',($scope: ng.IScope, $q: ng.IQService, $location: ng.ILocationService, $routeParams: ng.route.IRouteParamsService,
        InsightsBackendService, notificationFactory: INotificationFactory, staticObjects: IStaticObjects) => {
        var ctrl = new InsightsAddEditController($scope, $q, $location, $routeParams, InsightsBackendService, notificationFactory, staticObjects);
        return ctrl;
    });

}